#ifndef __MACROS_H__
  #define __MACROS_H__

#include "converter.h"

//////////////////////////////////////
// check(s)

#define INDEX_CHECK(actual, maximum) \
if (actual >= maximum) { \
string str_tmp1 = "(actual >= maximum) "; \
string str_tmp2; \
str_tmp1 += converter::to_string(actual, str_tmp2); \
str_tmp1 += ", "; \
str_tmp1 += converter::to_string(maximum, str_tmp2); \
throw index_exception(str_tmp1); }

#define INDEX_CHECK_MSG(actual, maximum, message) if (actual >= maximum) throw index_exception(message)

//////////////////////////////////////
// Unicode macro(s)

#ifdef _UNICODE
  #define tout wcout
  #define tstring wstring
  #define tostringstream wostringstream
#else
  #define tout cout
  #define tstring string
  #define tostringstream ostringstream
#endif

//////////////////////////////////////
// function(s)

#define POINTER_CHECK1(a) if (a == 0) return
#define POINTER_CHECK2(a, b) if (a == 0) return b
#define POINTER_CHECK_THROW(a) if (a == 0) throw pointer_exception("NULL POINTER")

#define MIN(a, b) (a < b ? a : b)
#define MAX(a, b) (a > b ? a : b)

#define ABS(a) (a < 0 ? -(a) : a)
#define SGN(a) (a > 0 ? 1 : (a == 0 ? 0 : -1))

#define SWAP(a, b) { a += b; b = a - b; a = a - b; }

#define STR(a) #a
#define CAT(a, b) a##b

#define IS_HEX(c) (isdigit((unsigned char) c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') ? true : false)

//////////////////////////////////////
// method(s)

#define PRINT_EXCEPTION_TO_CONSOLE(ge) cerr << ge.get_info() << endl << ge.get_message() << endl << ge.get_file_name() << " : " << ge.get_line() << endl

//////////////////////////////////////
// constant(s)

#define PI 3.14159265358979323846
#define E 2.7182818284590452354

#define PI_STR "3.14159265358979323846"
#define E_STR "2.7182818284590452354"

#ifndef SIZE_MAX
  #define SIZE_MAX string::npos
#endif

#define MINIMUM_SIZE_LIMIT_OMP 99

#endif
